Conversation
Synced from ~/.cursor/ with CLAUDE.md generation and skills symlink for Claude Code compatibility. Includes setup.sh for deploying to new machines.
Document the current repo structure, workflow skills, and shared scripts using the older conventions README format as a template.
task-review: resolve target repo by grepping code for concrete symbols, not task text. Title/description demoted to hints; prefix table kept as an exception shortcut; linked PRs short-circuit; cross-repo work splits into Asana subtasks. pr-create: drop all reviewer-assignment logic. Reviewer choice is a human step; status-setting and review-hour estimation went with it. --asana-attach remains. one-shot: stop defaulting --asana-assign. --asana-attach only. pr-land: add CHANGELOG placement warning handling so dated-release entries can be moved to Unreleased/staging before pushing.
- New slot-fixup.sh: slot HEAD fixup next to its target's group (used by pr-address and bugbot after each lint-commit.sh). - pr-finalize-fixups.sh: derive mode (autosquash | preserve) from the latest human activity on the PR; new squash-stale subcommand for the Fixups-A-before-B trigger; finalize action now push-only in preserve mode, autosquash+force-push in autosquash mode. - pr-address review-mode subcommand: returns mode + latestHumanActivity for shared use. - Simplified human-reviewer detection across pr-address and pr-land scripts: exclude only currentUser + bots (drop prAuthor exclusion). Works uniformly for solo and collab PRs — author gets no special treatment. - pr-address and bugbot SKILL.md: new Step 1.5 (squash-stale before address-pass) and per-fixup slot-fixup.sh after every lint-commit.sh.
- Pull-before-push gate: auto-fetch origin every run; abort --stage/--commit if origin is ahead. - Per-file divergence warnings: compare each affected path's most-recent commit timestamp to the local file's mtime; flag stale-local, deletion, and re-adding-deleted cases. - New JSON output fields: originBranch, originAhead, warnings. - SKILL.md: present new warnings in the dry-run summary; document the new policy and edge cases.
…nch-scan for legacy
| Checkout the PR branch to ensure file reads reflect the PR's code, not the current local branch: | ||
|
|
||
| ```bash | ||
| git fetch origin <headRef> && git checkout <headRef> |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
<headRef> is inserted unquoted into a shell command (git fetch ... && git checkout ...) even though PR branch names are attacker-controlled input.
Impact: A crafted branch name containing shell metacharacters (for example command substitution) can execute arbitrary commands in the review agent environment.
| Resolve the full 40-char SHA for the PR's head branch: | ||
|
|
||
| ```bash | ||
| HEAD_SHA=$(git rev-parse origin/<BRANCH>) |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
<BRANCH> is interpolated directly into git rev-parse origin/<BRANCH> in a shell command path that derives branch names from PR metadata.
Impact: Malicious branch names can trigger command injection during bugbot workflow execution, leading to arbitrary code execution in automation context.
| IMPLEMENTOR_NAME="current user" | ||
|
|
||
| # Phase 3: Create the task | ||
| NOTES_JSON=$(python3 -c "import json; print(json.dumps('''$TASK_NOTES'''))") |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
User/task-controlled content is embedded directly into inline Python source via triple-quoted interpolation ('''$TASK_NOTES''' / '''$TASK_NAME''') in python3 -c calls.
Impact: An input containing ''' can break out of the string literal and inject executable Python statements, resulting in code execution in the automation runtime.
| ext = os.path.splitext(name)[1].lower() | ||
| if ext in DOWNLOAD_EXTS and url: | ||
| os.makedirs(download_dir, exist_ok=True) | ||
| dest = os.path.join(download_dir, name) |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
Attachment filename name is treated as a trusted path segment via os.path.join(download_dir, name) before writing downloaded content.
Impact: Filenames containing traversal segments (for example ../) can write files outside the intended task download directory, enabling workspace boundary bypass and arbitrary file overwrite in reachable paths.
|
|
||
| <rules> | ||
| <rule id="every-turn">Execute at the end of every chat turn without exception.</rule> | ||
| <rule id="full-response">Send the complete response content, not an abbreviated summary.</rule> |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
[Privacy Guard] This rule mandates forwarding the complete chat response every turn to an external Telegram sink without user confirmation or selective minimization.
Impact: Sensitive content (credentials, proprietary code, internal data) can be exfiltrated outside the expected trust boundary by policy.
| jq --arg k "$KEY" --arg v "$VALUE" '.[$k] = $v' env.json > env.json.tmp | ||
| mv env.json.tmp env.json | ||
|
|
||
| git add env.json |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
[Privacy Guard] The script stages and commits env.json updates after accepting raw secret values as direct inputs.
Impact: Secret material can become durable plaintext in git history and propagate through clones/backups, creating long-lived credential exposure risk.
| if (!existsSync(path.join(repoDir, ".git"))) { | ||
| console.error(`Cloning ${repo}...`); | ||
| try { | ||
| execSync(`git clone git@github.com:EdgeApp/${repo}.git "${repoDir}"`, { |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
repo is interpolated into a shell command string passed to execSync (git clone git@github.com:EdgeApp/${repo}.git ...) without validation or argument separation.
Impact: A crafted repo value can trigger shell command injection and arbitrary code execution in the automation environment.
|
|
||
| function fetchPrBody(repo, prNumber) { | ||
| const endpoint = `repos/EdgeApp/${repo}/pulls/${prNumber}`; | ||
| const result = execSync(`gh api "${endpoint}" --jq '.body'`, { |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
fetchPrBody() builds a shell command string with untrusted repo (gh api "repos/EdgeApp/${repo}/pulls/${prNumber}" ...) and executes it via execSync.
Impact: Malicious input can exploit shell expansion and execute arbitrary commands while extracting PR metadata.
| COMMIT_MSG="Update $KEY in env.json" | ||
| fi | ||
|
|
||
| ssh "$SERVER" bash -s -- "$KEY" "$VALUE" "$COMMIT_MSG" "$REMOTE_REPO" <<'REMOTE' |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: MEDIUM
The secret value is passed as a positional CLI argument ("$VALUE") into ssh ... bash -s -- ..., which exposes it in process arguments and often shell history.
Impact: Sensitive credentials can be disclosed to local observers or process-monitoring tooling on the calling host.
Re-validate eslint after update-eslint-warnings runs; if the staged config fails lint (e.g. a naive graduation of a still-dirty file), restore eslint.config.mjs and abort. With this safety net in place, /pr-land's --skip-lint patch (e21dca8) is no longer needed — revert verify-repo.sh, pr-land-{prepare,merge}.sh, edge-repo.js, SKILL.md back to file-scoped lint. Also fixes pr-land-discover.sh's reviewer-state computation: only APPROVED/CHANGES_REQUESTED/DISMISSED change effective state, so a later COMMENTED reply doesn't shadow a prior APPROVED.
|
|
||
| function checkNpmPublished(packageName, version) { | ||
| try { | ||
| const info = execSync(`npm view ${packageName}@${version} version`, { |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
checkNpmPublished builds an execSync shell string using packageName and version from package.json (npm view ${packageName}@${version} version) without argument-safe execution.
Impact: A crafted package name/version can trigger command injection and arbitrary code execution in automation environments running this publish flow.
| const fileCount = changedFiles.split("\n").length; | ||
| console.log(`▶ eslint (${fileCount} changed file${fileCount === 1 ? "" : "s"} vs ${baseRef})...`); | ||
| const eslintResult = runCommandWithLog( | ||
| `npx eslint ${fileList}`, |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
verify-repo.sh builds an eslint command string from git-derived filenames and executes it via execSync; wrapping paths in quotes is not sufficient shell escaping.
Impact: A malicious filename in a branch can break command quoting and execute arbitrary shell commands during repository verification.
| "skills", | ||
| "verify-repo.sh" | ||
| ); | ||
| const baseArg = baseRef != null ? ` --base "${baseRef}"` : ""; |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
runVerification/related helpers interpolate derived repo/path values into execSync shell strings instead of passing argument arrays.
Impact: If attacker-influenced repo/path metadata reaches these call sites, command injection can occur during pr-land preparation/verification operations.
| </sub-step> | ||
| </step> | ||
|
|
||
| <step id="4" name="Upload to gist and clean up"> |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
The standup workflow templates externally sourced task/PR text directly into markdown and then requires uploading the rendered output to a persistent GitHub gist, without a mandatory scrub/redaction step.
Impact: Sensitive code-adjacent content (paths, snippets, internal details) from source systems can be durably exfiltrated to an external artifact.
| </sub-step> | ||
| </step> | ||
|
|
||
| <step id="4" name="Upload to gist and clean up"> |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
The HUDL flow maps GitHub-derived PR text fields into a generated markdown report and uploads it to a gist, but does not require sanitization/minimization of potentially sensitive content.
Impact: Code-related or sensitive operational details can leak into externally stored summaries.
| # Copy file only if changed, respecting --dry-run | ||
| sync_file() { | ||
| local src="$1" dest="$2" | ||
| if [[ ! -f "$dest" ]]; then |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
sync_file copies directly to destination paths without rejecting symlink destinations or enforcing canonical containment.
Impact: A pre-positioned symlink under the sync tree can redirect writes to unintended files, enabling arbitrary file overwrite as the current user.
| for oc_skill_dir in "$OPENCODE_DIR"/skills/*/; do | ||
| [[ -d "$oc_skill_dir" ]] || continue | ||
| local name | ||
| name=$(basename "$oc_skill_dir") |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
Cleanup uses rm -rf on globbed skill directories without symlink validation.
Impact: A symlinked directory entry can cause deletion outside the intended sync root, leading to destructive data loss in attacker-chosen paths.


edge-dev-agents
Complete agent-assisted development workflow for Edge repositories:
slash skills, companion scripts, coding standards, review standards,
and meta-tooling for maintaining the workflow itself.
The distributable Cursor content lives under
.cursor/. This repo is theversioned home for those skills, rules, scripts, and docs.
The canonical local doc lives at
~/.cursor/README.md. During/convention-sync, that file is mirrored toedge-dev-agents/README.md, andthe repo copy should not keep a second
.cursor/README.md.Installation
1. Set the required env var in your
~/.zshrc:This drives branch naming and PR discovery across the workflow.
2. Sync the repo copy into
~/.cursor/:This repo treats
~/.cursor/as the canonical working copy. Use/convention-syncto move local changes intoedge-dev-agents, or run thecompanion script directly when onboarding:
~/.cursor/skills/convention-sync/scripts/convention-sync.sh \ --repo-to-user --stage3. Verify prerequisites:
ghCLI:gh auth loginjq:brew install jqASANA_TOKENenv var for Asana-backed workflowsTable of Contents
Architecture
Separation of concerns:
SKILL.md) define workflows, rules, and step ordering..sh,.js) handle deterministic work like git,GitHub, Asana, and JSON processing.
.mdc) provide persistent guidance that gets loaded by context.together.
All GitHub API work uses
ghCLI. Deterministic git operations should live inscripts, not be re-described independently across skills.
Skills (Slash Skills)
Core Implementation
/im/one-shot/pr-create/dep-pr/changelogPlanning and Context
/asana-plan/task-review/qReview and Landing
/pr-review/pr-address/pr-land/staging-cherry-pickAsana and Utility
/asana-task-update/standup/chat-audit/convention-sync~/.cursor/with this repo, mirror the local README to repo root, and update PR descriptions fromREADME.md/author/fix-eslintCompanion Scripts
PR Operations
pr-create.shgh pr createpr-address.shgh apiREST + GraphQLgithub-pr-review.shgh pr view+gh apigithub-pr-activity.shgh api graphqlPR Landing Pipeline (
/pr-land)pr-land-discover.shpr-land-comments.shgit-branch-ops.shpr-land-prepare.shpr-land-merge.shpr-land-publish.shpr-land-extract-asana-task.shupgrade-dep.shdevelopfirst.staging-cherry-pick.shstagingverify-repo.shBuild, Lint, and Analysis
lint-commit.shlint-warnings.shinstall-deps.shcursor-chat-extract.jsAsana and Portability
asana-get-context.shasana-task-update.shasana-create-dep-task.shasana-whoami.shconvention-sync.sh~/.cursor/andedge-dev-agentsin either direction, mirroring~/.cursor/README.mdto repo rootREADME.mdgenerate-claude-md.sh~/.claude/CLAUDE.mdfrom always-apply rulestool-sync.shport-to-opencode.shShared Modules
edge-repo.jsghhelpers for thepr-landpipelineRules (
.mdcfiles)workflow-halt-on-error.mdcload-standards-by-filetype.mdcanswer-questions-first.mdcno-format-lint.mdctypescript-standards.mdcreview-standards.mdceslint-warnings.mdcafter_each_chat.mdcDesign Principles
work belongs in shared scripts.
ghover raw GitHub HTTP calls. Use the authenticated CLI for GitHubworkflows.
should live in one script and be consumed by multiple skills.
evaluating lint/type failures.
script instead of patching around it in an ad-hoc way.
~/.cursor/is the working source of truth;edge-dev-agentsis the distribution and review copy.